#! /usr/bin/python

##
#   sprintf(speeds_sql,"SELECT time, speed FROM today_cross_times WHERE seg_ref_id=%d ORDER BY time;",
##
	
"""
convert osm file to freemap rdb file.

this script reads an osm xml file and produces 6 text files:
  "roads_sql"
  "roads_route_sql"
  "country_borders_sql"
  "water_sq"
  "turn_restrictions_sql"
  "cities_sql"

each text file is a simulation of an sql answer for a query made by
buildmap (see buildmap_postgres.c). buildmap is the tool for creating
roadmap/freemap rdb files.

all these text files are then given to a patched buildmap exeutable.
the patched executable gets its sql answers from the text files
instead of postgres db.

buildmap does not use the column names. therefore, the format of the
text files is simply one text row per sql column.

roads_sql
	segments.id AS id, 
	AsText(simplify(segments.the_geom,  "SIMPLIFICATION")) AS the_geom,
	segments.road_type AS layer,
	segments.from_node AS from_node_id,
	segments.to_node AS to_node_id,
	street_types.name AS street_type,
	streets.name AS street_name,
	streets.text2speech as text2speech,
	cities.name as city_name,
	fraddl,
	toaddl,
	fraddr,
	toaddr,
	from_travel_ref,
	to_travel_ref

roads_route_sql
	segments.id AS id,
	segments.from_car_allowed AS from_car_allowed,
	segments.to_car_allowed AS to_car_allowed,
	segments.from_max_speed AS from_max_speed,
	segments.to_max_speed AS to_max_speed,
	segments.from_cross_speed AS from_cross_speed,
	segments.to_cross_speed AS to_cross_speed,
	segments.road_type AS layer
	FROM segments


country_borders_sql
	id AS id
	AsText(simplify(the_geom,  0.0001)) AS the_geom
	FROM borders;";

water_sql
	id AS id
	AsText(simplify(the_geom,  0.0001)) AS the_geom
	FROM water;";

turn_restrictions_sql
	node_id
	seg1_id
	seg2_id
	FROM turn_restrictions;";

cities_sql
	name
	FROM cities;";

"""


ROADMAP_ROAD_FIRST      = 1
ROADMAP_ROAD_FREEWAY    = 1
ROADMAP_ROAD_PRIMARY    = 2
ROADMAP_ROAD_SECONDARY  = 3
ROADMAP_ROAD_RAMP       = 4
ROADMAP_ROAD_MAIN       = 5
ROADMAP_ROAD_EXIT       = 6
ROADMAP_ROAD_STREET     = 7
ROADMAP_ROAD_PEDESTRIAN = 8
ROADMAP_ROAD_4X4        = 9
ROADMAP_ROAD_TRAIL      =10 
ROADMAP_ROAD_WALKWAY    =11
ROADMAP_ROAD_LAST       =11
ROADMAP_AREA_FIRST      =12
ROADMAP_AREA_PARC       =12
ROADMAP_AREA_HOSPITAL   =13
ROADMAP_AREA_AIRPORT    =14
ROADMAP_AREA_STATION    =15
ROADMAP_AREA_MALL       =16
ROADMAP_AREA_LAST       =16
ROADMAP_WATER_FIRST     =17
ROADMAP_WATER_SHORELINE =17
ROADMAP_WATER_RIVER     =18
ROADMAP_WATER_LAKE      =19
ROADMAP_WATER_SEA       =20
ROADMAP_WATER_LAST      =20
ROADMAP_CATEGORY_RANGE  =20
def get_way_cfcc_type(way):
    w = way # todo: change "w" to "way"
    if w.tags.has_key("highway"):
	    if w.tags["highway"] == "motorway":
		    return ROADMAP_ROAD_FREEWAY
	    elif w.tags["highway"] == "motorway_link":
		    return ROADMAP_ROAD_RAMP
	    elif w.tags["highway"] == "trunk":
		    return ROADMAP_ROAD_FREEWAY
	    elif w.tags["highway"] == "trunk_link":
		    return ROADMAP_ROAD_RAMP
	    elif w.tags["highway"] == "primary":
		    return ROADMAP_ROAD_PRIMARY
	    elif w.tags["highway"] == "primary_link":
		    return ROADMAP_ROAD_RAMP
	    elif w.tags["highway"] == "secondary":
		    return ROADMAP_ROAD_SECONDARY
	    elif w.tags["highway"] == "tertiary":
		    return ROADMAP_ROAD_MAIN
	    elif w.tags["highway"] == "unclassified":
		    return ROADMAP_ROAD_STREET
	    elif w.tags["highway"] == "residential":
		    return ROADMAP_ROAD_STREET
	    elif w.tags["highway"] == "living_street":
		    return ROADMAP_ROAD_PEDESTRIAN
	    elif w.tags["highway"] == "pedestrian":
		    return ROADMAP_ROAD_PEDESTRIAN
	    elif w.tags["highway"] == "steps":
		    return ROADMAP_ROAD_WALKWAY
	    elif w.tags["highway"] == "footway" or w.tags["highway"] == "footpath":
		    return ROADMAP_ROAD_WALKWAY
	    else:
		    return ROADMAP_ROAD_STREET
    elif w.tags.has_key("railway"):
	    return ROADMAP_ROAD_TRAIL  # TODO this is a patch. no proper cfcc type for this??
    elif w.tags.has_key("waterway"):
	    return ROADMAP_WATER_FIRST # TODO use more specific types
    elif w.tags.has_key("natural") and w.tags["natural"]=="water":
	    return ROADMAP_WATER_FIRST # TODO use more specific types
    else:
	    # TODO: support area and water types
	    return ROADMAP_ROAD_STREET

def get_way_db_type(way):
	cfcc = get_way_cfcc_type(way)
	if cfcc == ROADMAP_ROAD_STREET:
		return 1
	if cfcc == ROADMAP_ROAD_MAIN:
		return 2
	if cfcc == ROADMAP_ROAD_FREEWAY:
		return 3
	if cfcc == ROADMAP_ROAD_PRIMARY:
		return 6
	if cfcc == ROADMAP_ROAD_SECONDARY:
		return 7
	if cfcc == ROADMAP_ROAD_RAMP:
		return 4
	if cfcc == ROADMAP_ROAD_TRAIL:
		return 5
	if cfcc == ROADMAP_ROAD_4X4:
		return 8
	if cfcc == ROADMAP_ROAD_WALKWAY:
		return 9
	if cfcc == ROADMAP_ROAD_PEDESTRIAN:
		return 10
	if cfcc == ROADMAP_ROAD_EXIT:
		return 11
	if cfcc == ROADMAP_ROAD_STREET:
		return 12
	return 12

########### main ##############

from python_osm import *
import sys

if len(sys.argv)!=2:
	print """
Usage: osm_to_roadmap2.py <input_file>

Reads an osm xml file and writes several text files which can be fed to the buildmap app, which produces an rdb file.

input_file    input file name, or '-' for standard input.

output file:
              roads_sql
              roads_route_sql
              country_borders_sql
              water_sql
              turn_restrictions_sql
              cities_sql

examples:
	      ./osm_to_roadmap2.py wien-ostereich.osm
	      ./osm_to_roadmap2.py - < wien-ostereich.osm
"""
	exit(-1)

infile = sys.argv[1]
if sys.argv[1]=="-":
	infile = sys.stdin

osm = OSMXMLFile(infile)

print "num nodes - ", len(osm.nodes)
print "num ways - ", len(osm.ways)
print "num relation - ", len(osm.relations)

# point id must fit in dword
min_node_id = min([int(node.id) for node in osm.nodes])
max_node_id = max([int(node.id) for node in osm.nodes])
assert min_node_id > 0
assert max_node_id < 0x7FFFFFFF

# todo: same check for lines

# open all files
roads_sql            =open("roads_sql","wt")
roads_route_sql      =open("roads_route_sql","wt")
country_borders_sql  =open("country_borders_sql","wt")
water_sql            =open("water_sql","wt")
turn_restrictions_sql=open("turn_restrictions_sql","wt")
cities_sql           =open("cities_sql","wt")


###
### create roads_sql file ###
###
for w in osm.ways:
    if len(w.nodes)<2:
	    continue	# ignore ways with zero or one nodes
    for node_index in range(1,len(w.nodes)):
	# warning segments.id is a 32bit int. w.id has no limit...
	#print >>roads_sql, w.id  # segments.id AS id
	
	# for now, don't give segments.id / tlid
	print >>roads_sql, "[id]"    # segments.id AS id
	
	#AsText(simplify(segments.the_geom,0.0001)) AS the_geom,
	the_geom = "LINESTRING(%.4f %.4f,%.4f %.4f)" % \
	             (float(w.nodes[node_index-1].lon),
		      float(w.nodes[node_index-1].lat),
		      float(w.nodes[node_index  ].lon),
		      float(w.nodes[node_index  ].lat))
	
	print >>roads_sql, "[the_geom]"+the_geom
	
	#segments.road_type AS layer,
	print >>roads_sql, "[layer]"+str(get_way_db_type(w))
	
	#segments.from_node AS from_node_id,
	print >>roads_sql, "[from_node_id]-1"
	
	#segments.to_node AS to_node_id,
	print >>roads_sql, "[to_node_id]-1"
	
	#street_types.name AS street_type,
	print >>roads_sql, "[street_type]"
	
	#streets.name AS street_name,
	if w.tags.has_key("name"):
			print >>roads_sql, "[street_name]"+w.tags["name"].encode('utf-8')
	else:
			print >>roads_sql, "[street_name]"
	
	#streets.text2speech as text2speech,
	print >>roads_sql, "[text2speech]"
	
	#cities.name as city_name,
	print >>roads_sql, "[roads_sql]"
	
	#fraddl,
	print >>roads_sql, "[fraddl]"
	
	#toaddl,
	print >>roads_sql, "[toaddl]"
	
	#fraddr,
	print >>roads_sql, "[fraddr]"
	
	#toaddr,
	print >>roads_sql, "[toaddr]"
	
	#from_travel_ref,
	print >>roads_sql, "[from_travel_ref]"
	
	#to_travel_ref
	print >>roads_sql, "[to_travel_ref]"
	
	#if w.tags.has_key("highway"):
	#    cfcc = get_way_cfcc_type(w)


###
### create country_borders_sql file ###
###
for n in osm.ways:
	if len(w.nodes)<2:
		continue	# ignore ways with zero or one nodes
	if n.tags.has_key("border_type") and n.tags["border_type"] == "nation":
		# write name
		# for now, don't give id / tlid
		print >>country_borders_sql, ""    # id
		
		# AsText(simplify(the_geom,  0.0001)) AS the_geom
		the_geom = "LINESTRING("
		for i in range(0,len(w.nodes)):
			n = w.nodes[i]
			# after every point (except the last one) add ","
			if i > 0:
				the_geom += ","
			the_geom += "%.4f %.4f" % (float(n.lon),float(n.lat))
		the_geom += ")"
		print >>country_borders_sql, the_geom

###
### create water_sql file ###
###
# way:
#   waterway=*   [area=yes]
#      or
#   natural=water [area=yes]
#way: <tag k='waterway' v='canal' />
#way: <tag k='waterway' v='river' />
#
#<tag k='area' v='yes' />
#<tag k='name' v='YAM HAMELACH' />
#<tag k='natural' v='water' />



###
### create turn_restrictions_sql file ###
###

###
### create cities_sql file ###
###
for n in osm.nodes:
	if n.tags.has_key("place") and n.tags.has_key("name"):
		# write name
		print >>cities_sql, "[name]"+n.tags["name"].encode('utf-8')

# close all files
roads_sql            .close()
roads_route_sql      .close()
country_borders_sql  .close()
water_sql            .close()
turn_restrictions_sql.close()
cities_sql           .close()

exit(0)
###################################################################################3
osm = None # free the memory?
